﻿/**************************************************************
*作者：Leon
*创建时间：2022/4/5 17:28:42
**************************************************************/
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Input;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;

namespace Lad.DrawProject.Controls;

public partial class ScrollViewCanvasViewModel : ObservableObject, IBaseCanvasViewModel
{
    private IDiagramServiceProvider? serviceProvider;
    public IDiagramServiceProvider ServiceProvider { get {
            serviceProvider ??= DiagramServicesProvider.Instance;
            serviceProvider.CanvasViewModel ??= this;
            return serviceProvider;
        } }
    public ObservableCollection<SelectableItemViewModelBase> Items { get; set; } = new();

    public List<SelectableItemViewModelBase> SelectedItems => Items.Where(x => x.IsSelected).ToList();
    private SelectionService? selectionService;
    public SelectionService SelectionService => selectionService ??= new(this);
    private double _ZoomValue;

    public double ZoomValue
    {
        get { return _ZoomValue; }
        set { SetProperty(ref _ZoomValue, value); }
    }


    public Func<SelectableItemViewModelBase, bool>? OutAddVerify { get; set; }
    

    public ScrollViewCanvasViewModel()
    {
        _ZoomValue = 1;
        Items.CollectionChanged += Items_CollectionChanged;
        ActionManager.PropertyChanged += ActionManager_PropertyChanged;
        ServiceProvider.PropertyChanged += ServiceProvider_PropertyChanged;

#if DEBUG
        Add(new DataControlDemo()
        {
            Width = DipHelper.MmToDip(2000),
            Height = DipHelper.MmToDip(60),
            Top = DipHelper.MmToDip(40),
            Left = DipHelper.MmToDip(200),
            ParentId = Guid.Empty,
            Icon = "M 0,0 H 60 V 40 C 30,30 30,50 0,40 Z",
            IsHitTestVisible = true,
            ShowText=true,
            Text="BXMH001"
        });
        Add(new DataControlDemo() {
            Width = DipHelper.MmToDip(2000),
            Height = DipHelper.MmToDip(60),
            Top = DipHelper.MmToDip(180),
            Left = DipHelper.MmToDip(200),
            ParentId = Guid.Empty,
            Icon = "M 0,0 H 60 V 40 C 30,30 30,50 0,40 Z",
            IsHitTestVisible = true,
            ShowText = false
        });

        Add(new DataControlDemo() {
            Width = DipHelper.MmToDip(2000),
            Height = DipHelper.MmToDip(60),
            Top = DipHelper.MmToDip(3540),
            Left = DipHelper.MmToDip(200),

            ParentId = Guid.Empty,
            Icon = "M 0,0 H 60 V 40 C 30,30 30,50 0,40 Z",
            IsHitTestVisible = true,
            ShowText = false
        });
        Add(new DataControlDemo() {
            Width = DipHelper.MmToDip(2000),
            Height = DipHelper.MmToDip(60),
            Top = DipHelper.MmToDip(3680),
            Left = DipHelper.MmToDip(200),
            ParentId = Guid.Empty,
            Icon = "M 0,0 H 60 V 40 C 30,30 30,50 0,40 Z",
            IsHitTestVisible = true,
            ShowText = false
        });
#endif   
    }


    public bool BelongToSameGroup(IGroupable item1, IGroupable item2)
    {
        IGroupable? root1 = SelectionService.GetGroupRoot(item1);
        IGroupable? root2 = SelectionService.GetGroupRoot(item2);

        return (root1?.Id == root2?.Id);
    }

    public Rect GetBoundingRectangle(IEnumerable<DesignerItemViewModelBase> items)
    {
        throw new NotImplementedException();
    }

    public void UpdateZIndex()
    {
        var ordered = Items.OrderBy(p => p.ZIndex).ToList();
        for (int i = 0; i < ordered.Count; i++)
            ordered[i].ZIndex = i;
    }

    /// <summary>
    /// 添加条目的方法
    /// </summary>
    /// <param name="item"></param>
    private void Add(SelectableItemViewModelBase item)
    {
        item.ZIndex = Items.Count;
        item.Id = Guid.NewGuid();
        Items.Add(item);
        item.IsSelected = true;
    }

    void IBaseCanvasViewModel.Zoom(double value)
    {
        ServiceProvider.ActionManager.DoAction(new ZommAction(this, value));
    }
}


/// <summary>
/// 属性事件
/// </summary>
partial class ScrollViewCanvasViewModel
{
    /// <summary>
    /// 快速样式
    /// </summary>
    public IQuickThemeViewModel QuickThemeViewModel
    {
        get { return ServiceProvider.QuickThemeViewModel;}
    }

    private SelectableItemViewModelBase? _SelectedItem;

    public SelectableItemViewModelBase? SelectedItem
    {
        get { return _SelectedItem; }
        set { SetProperty(ref _SelectedItem, value); }
    }


    private void ServiceProvider_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        OnPropertyChanged(e);
        var quickThemeViewModel = QuickThemeViewModel;
        if (e.PropertyName == nameof(QuickTheme) && quickThemeViewModel.QuickTheme != null)
        {
            SetFont(quickThemeViewModel.QuickTheme.FontViewModel!, "FontColor");
            SetColor(quickThemeViewModel.QuickTheme.ColorViewModel!, "FillColor");
            SetColor(quickThemeViewModel.QuickTheme.ColorViewModel!, "LineColor");
            SetColor(quickThemeViewModel.QuickTheme.ColorViewModel!, "LineWidth");
            OnPropertyChanged(nameof(FontViewModel));
            OnPropertyChanged(nameof(ColorViewModel));
        }
        void SetFont(IFontViewModel fontViewModel, string propertyName)
        {
            foreach (var item in SelectedItems)
            {
                if (item.FontViewModel != fontViewModel)
                {
                    CopyHelper.CopyPropertyValue(fontViewModel, item.FontViewModel!, propertyName);

                }
            }
        }
        void SetColor(IColorViewModel colorViewModel, string propertyName)
        {
            foreach (var item in SelectedItems)
            {
                if (item.ColorViewModel != colorViewModel)
                {
                    CopyHelper.CopyPropertyValue(colorViewModel, item.ColorViewModel, propertyName);
                }
            }
        }
    }

    private void ActionManager_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        UndoCommand.NotifyCanExecuteChanged();
        RedoCommand.NotifyCanExecuteChanged();
    }

    private void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (e.OldItems != null)
        {
            foreach (var item in e.OldItems.OfType<SelectableItemViewModelBase>())
            {
                item.PropertyChanged += Item_PropertyChanged;
            }
        }
        if (e.NewItems != null)
        {
            foreach (var item in e.NewItems.OfType<SelectableItemViewModelBase>())
            {
                item.PropertyChanged += Item_PropertyChanged;
            }
        }
        OnPropertyChanged(nameof(Items));
    }

    private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        OnPropertyChanged(e.PropertyName);
        if (e.PropertyName == "IsSelected")
        {
            SelectedItem = Items.FirstOrDefault(x => x.IsSelected);
        }
    }
}




public interface IBaseCanvasViewModel : INotifyPropertyChanged
{

    /// <summary>
    /// 选择的对象集合
    /// </summary>
    List<SelectableItemViewModelBase> SelectedItems { get; }

    /// <summary>
    /// 画布中的绑定的对象集合
    /// </summary>
    ObservableCollection<SelectableItemViewModelBase> Items { get; }

    /// <summary>
    /// 选择服务
    /// </summary>
    SelectionService SelectionService { get; }

    /// <summary>
    /// 创建新的画布
    /// </summary>
    IRelayCommand CreateNewDiagramCommand { get; }

    /// <summary>
    /// 直接添加条目
    /// 备注：添加单个对象，或者List集合，不支持撤销
    /// </summary>
    IRelayCommand DirectAddItemCommand { get; }

    /// <summary>
    /// 添加对象到画布集合
    /// 备注：添加单个对象，或者List集合，支持撤销
    /// </summary>
    IRelayCommand AddItemCommand { get; }

    /// <summary>
    /// 移除条目
    /// 备注：移除单个条目，或者移除List集合，同时移除撤销管理
    /// </summary>
    IRelayCommand RemoveItemCommand { get; }

    /// <summary>
    /// 直接移除条目
    /// 备注：移除单个条目，或者移除List集合，不进行撤销管理
    /// </summary>
    IRelayCommand DirectRemoveItemCommand { get; }

    /// <summary>
    /// 清空选择条目
    /// </summary>
    IRelayCommand ClearSelectedItemsCommand { get; }

    /// <summary>
    /// 选择的 DesignerItemViewModelBase 条目执行顶部对齐命令
    /// 备注：支持撤销
    /// </summary>
    IRelayCommand AlignTopCommand { get; }

    /// <summary>
    /// 选择的 DesignerItemViewModelBase 条目执行垂直居中对齐命令
    /// 备注：支持撤销
    /// </summary>
    IRelayCommand AlignVerticalCentersCommand { get; }

    /// <summary>
    /// 选择的 DesignerItemViewModelBase 条目执行垂直底部对齐命令
    /// 备注：支持撤销
    /// </summary>
    IRelayCommand AlignBottomCommand { get; }

    /// <summary>
    /// 选择的 DesignerItemViewModelBase 条目执行垂直左对齐命令
    /// 备注：支持撤销
    /// </summary>
    IRelayCommand AlignLeftCommand { get; }

    /// <summary>
    /// 选择的 DesignerItemViewModelBase 条目执行水平居中对齐命令
    /// 备注：支持撤销
    /// </summary>
    IRelayCommand AlignHorizontalCentersCommand { get; }

    /// <summary>
    /// 选择的 DesignerItemViewModelBase 条目执行右对齐命令
    /// 备注：支持撤销
    /// </summary>
    IRelayCommand AlignRightCommand { get; }

    /// <summary>
    /// 执行选择的 SelectableDesignerItemViewModelBase 条目上移一层的命令
    /// 备注：支持撤销
    /// </summary>
    IRelayCommand BringForwardCommand { get; }

    /// <summary>
    /// 执行选择的 SelectableDesignerItemViewModelBase 条目置为顶层的命令
    /// 备注：支持撤销
    /// </summary>
    IRelayCommand BringToFrontCommand { get; }

    /// <summary>
    /// 执行选择的 SelectableDesignerItemViewModelBase 条目后移一层的命令
    /// 备注：支持撤销
    /// </summary>
    IRelayCommand SendBackwardCommand { get; }

    /// <summary>
    /// 执行选择的 SelectableDesignerItemViewModelBase 条目置为底层的命令
    /// 备注：支持撤销
    /// </summary>
    IRelayCommand SendToBackCommand { get; }

    /// <summary>
    /// 执行选择的 DesignerItemViewModelBase 条目 水平分布对齐的命令
    /// 备注：支持撤销
    /// </summary>
    IRelayCommand DistributeHorizontalCommand { get; }

    /// <summary>
    /// 执行选择的 DesignerItemViewModelBase 条目 垂直分布对齐的命令
    /// 备注：支持撤销
    /// </summary>
    IRelayCommand DistributeVerticalCommand { get; }

    /// <summary>
    /// 选择所有条目
    /// </summary>
    IRelayCommand SelectAllCommand { get; }

    /// <summary>
    /// 撤销操作
    /// </summary>
    IRelayCommand UndoCommand { get; }

    /// <summary>
    /// 恢复操作
    /// </summary>
    IRelayCommand RedoCommand { get; }

    /// <summary>
    /// 数据验证委托
    /// </summary>
    Func<SelectableItemViewModelBase, bool>? OutAddVerify { get; set; }

    /// <summary>
    /// 清空选择条目
    /// </summary>
    void ClearSelectedItems();

    /// <summary>
    /// 判断条目是否属于相同组
    /// </summary>
    /// <param name="item1"></param>
    /// <param name="item2"></param>
    /// <returns></returns>
    bool BelongToSameGroup(IGroupable item1, IGroupable item2);

    /// <summary>
    /// 获取 DesignerItemViewModelBase 边框范围
    /// </summary>
    /// <param name="items"></param>
    /// <returns></returns>
    Rect GetBoundingRectangle(IEnumerable<DesignerItemViewModelBase> items);

    /// <summary>
    /// 更新Z索引
    /// </summary>
    void UpdateZIndex();

    double ZoomValue { get; set; }

    internal void Zoom(double value);
}
